﻿#pragma once

#include "../repo/src/include/root/rpc_transport.h"
#include <cstdint>

// 前置声明，依赖knet
typedef struct _ringbuffer_t kringbuffer_t;

namespace kratos {
namespace service {

// 容器网络接口
class BoxNetwork;

/**
 * RPC管道实现类
 * @see rpc::Transport.
 */
class BoxChannel : public rpc::Transport {
  kringbuffer_t *rb_{nullptr}; ///< 缓冲区, 暂存从网络线程接收到的数据
  BoxNetwork *network_{nullptr}; ///< 网络实例

  std::string channel_name_; ///< 管道名称
  std::string
      coro_listener_name_; ///< 协程监听器名称, 名字对应在协程内启动的监听器

  std::uint64_t user_data_{0};  ///< 用户数据
  std::uint64_t channel_id_{0}; ///< 管道ID

  rpc::Address local_addr_; ///< 本地地址
  rpc::Address peer_addr_;  ///< 远端地址

  bool is_close_{false}; ///< 关闭标志

public:
  /**
   * 构造函数
   *
   * \param channel_id 管道ID
   * \param network    网络实例
   * \param name       管道名称
   */
  BoxChannel(std::uint64_t channel_id, BoxNetwork *network,
             const std::string &name);
  /**
   * 析构
   */
  virtual ~BoxChannel();
  /**
   * @see rpc::Transport::send
   */
  virtual int send(const char *data, const int size) override;
  /**
   * @see rpc::Transport::peek
   */
  virtual int peek(char *data, const int size) override;
  /**
   * @see rpc::Transport::recv
   */
  virtual int recv(char *data, const int size) override;
  /**
   * @see rpc::Transport::skip
   */
  virtual int skip(const int size) override;
  /**
   * @see rpc::Transport::size
   */
  virtual int size() override;
  /**
   * @see rpc::Transport::isClose
   */
  virtual bool isClose() override;
  /**
   * @see rpc::Transport::close
   */
  virtual void close() override;
  /**
   * @brief Get local address of transport
   * @return Address instance
   */
  virtual const rpc::Address& getLocalAddress() override;
  /**
   * @brief Get remote peer address of transport
   * @return Address instance
   */
  virtual const rpc::Address& getPeerAddress() override;
  /**
   * 取得管道ID
   *
   * \return 管道ID
   */
  auto get_id() const noexcept -> std::uint64_t;
  /**
   * 将从对端接收到的数据写入读缓冲区
   *
   * \param data 数据指针
   * \param size 数据长度, 字节
   * \return 实际写入的长度
   */
  auto write_buffer(const char *data, int size) noexcept -> int;
  /**
   * 设置关闭标志为true
   */
  auto set_close_flag() noexcept -> void;
  /**
   * 返回管道名称
   *
   * \return 管道名称
   */
  auto get_channel_name() const noexcept -> const std::string &;
  /**
   * 设置管道名称.
   *
   * \param name 管道名称.
   * \return
   */
  auto set_channel_name(const std::string &name) noexcept -> void;
  /**
   * 设置协程监听器名称.
   *
   * \param name 协程监听器名称.
   * \return
   */
  auto set_coro_listener_name(const std::string &name) noexcept -> void;
  /**
   * 获取协程监听器名称.
   *
   * \return 协程监听器名称.
   */
  auto get_coro_listener_name() const noexcept -> const std::string &;
  /**
   * 设置用户数据.
   *
   * \param user_data 用户数据
   * \return
   */
  auto set_user_data(std::uint64_t user_data) noexcept -> void;
  /**
   * 获取用户数据.
   *
   * \return 用户数据
   */
  auto get_user_data() const noexcept -> std::uint64_t;
  /**
   * 获取用户数据.
   *
   * \return 用户数据
   */
  template <typename T> auto cast_user_data() noexcept -> T {
    return reinterpret_cast<T>(user_data_);
  }
  /**
   * @brief 设置地址信息
   * @param local 本地地址
   * @param peer 远端地址
   * @return
   */
  auto set_address(const rpc::Address &local, const rpc::Address &peer) -> void;
};

} // namespace service
} // namespace kratos
